import datetime
from django.contrib import messages
from django.core.urlresolvers import reverse_lazy
from django.views.generic import TemplateView, ListView
from django.shortcuts import get_object_or_404, redirect
from django.utils import timezone

from common.forms import SelectAssigneeForm
from common.mixins import UserCourseRelatedMixin, PageinatorMixin
from common.utils import get_dt
from course.models import Course
from course.views import SidebarMixin
from task.models import Task
from .forms import ExamForm, ProblemFormset
from .models import ExamPaper, Exam, Answer


class ExamSummaryView(SidebarMixin, UserCourseRelatedMixin, TemplateView):

    template_name = 'exam/summary.html'
    section_title = 'exam summary'

    def dispatch(self, request, exam_id):
        self.exam = get_object_or_404(Exam, id=exam_id)
        self.course = self.exam.course
        self.course_id = self.course.id
        return super(ExamSummaryView, self).dispatch(request, exam_id)

    def get(self, request, exam_id):
        exam = get_object_or_404(Exam, id=exam_id)
        students = exam.course.students.all()
        obj_list = []
        sum_students = 0
        sum_exam_students = 0
        sum_score_students = 0
        sum_score = 0
        avg_score = 0
        for stu in students:
            sum_students = sum_students + 1
            obj = {}
            obj['user_id'] = stu.id
            obj['name'] = stu.username
            obj['module_id'] = exam.id
            exam_paper = ExamPaper.objects.filter(student=stu, exam=exam)
            if exam_paper:
                obj['exam_paper_id'] = exam_paper[0].id
                sum_exam_students = sum_exam_students + 1
                obj['score'] = exam_paper[0].total_score
                if obj['score'] is not None:
                    sum_score_students = sum_score_students + 1
                    sum_score = sum_score + obj['score']
                else:
                    obj['score'] = 'not scored yet'
            else:
                obj['score'] = 'not answered yet'
            obj_list.append(obj)
        if sum_score_students != 0:
            avg_score = sum_score / sum_score_students
        else:
            avg_score = ''

        return self.render_to_response({
            'view': self,
            'obj_list': obj_list,
            'sum_students': sum_students,
            'avg_score': avg_score,
            'sum_exam_students': sum_exam_students
        })


class ExamStudentView(TemplateView):
    template_name = 'exam/student.html'
    exam = None

    def dispatch(self, request, exam_id):
        self.exam = get_object_or_404(Exam, id=exam_id,)

        return super(ExamStudentView, self).dispatch(request, exam_id)

    def get(self, request, exam_id):
        exam_paper, created = ExamPaper.objects.get_or_create(
            exam=self.exam, student=self.request.user)
        Answer.objects.init_answer(exam_paper)
        ExamPaper.objects.init_exam_paper(
            self.exam, self.request.user)

        return self.render_to_response({
            'view': self,
            'exam': self.exam,
            'is_exam_ended': self.exam.is_ended(),
        })

    def post(self, request, exam_id):
        answer = Answer.objects.get(pk=request.POST.get("answer_pk"))
        if 'content' in request.POST:
            present = timezone.now()
            start = self.exam.started_time
            end = start + datetime.timedelta(
                minutes=answer.problem.minutes)
            # print(start, present, end)
            if start < present and present < end:
                answer.content = request.POST.get("content")
                answer.save()
                messages.info(request, 'updated')
            else:
                # invalid answer time
                messages.error(request, 'invalid answer time')
        elif 'amendment' in request.POST:
            answer.amendment = request.POST.get('amendment')
            answer.save()
            messages.info(request, 'updated')

        return self.render_to_response({
            'view': self,
            'exam': self.exam,
            'is_exam_ended': self.exam.is_ended(),
        })


class ExamTeacherView(UserCourseRelatedMixin, SidebarMixin, TemplateView):
    template_name = 'exam/teacher.html'
    section_title = 'Create Exam'

    course = None
    exam = None

    def dispatch(self, request, course_id, exam_id=None):
        self.course = get_object_or_404(Course, id=course_id)
        self.course_id = course_id
        if exam_id:
            self.exam = get_object_or_404(Exam, id=exam_id)
            self.section_title = 'Edit Exam'
        self.success_url = reverse_lazy(
            'course:calendar', kwargs={'pk': course_id})
        return super(ExamTeacherView, self).dispatch(
            request, course_id, exam_id)

    def get(self, request, course_id, exam_id=None):
        if not exam_id:
            dt = get_dt(request.GET['year'],
                        request.GET['month'], request.GET['day'])
            data = {
                'start': dt,
                'end': dt,
                'course': self.course,
            }
            form = ExamForm(initial=data)
        else:
            form = ExamForm(instance=self.exam)
        formset = ProblemFormset(instance=self.exam)

        return self.render_to_response({
            'view': self,
            'form': form,
            'formset': formset,
        })

    def post(self, request, course_id, exam_id=None):
        pre_started = (self.exam and self.exam.started)
        form = ExamForm(data=request.POST, instance=self.exam)
        formset = ProblemFormset(request.POST, instance=self.exam)
        if form.is_valid() and formset.is_valid():
            exam = form.save()
            started_changed = (self.exam and pre_started != exam.started)
            if started_changed:
                if exam.started:
                    exam.started_time = timezone.now()
                else:
                    exam.started_time = None
                exam.save()

            problems = formset.save(commit=False)
            for problem in problems:
                problem.exam = exam
                problem.save()
            for problem in formset.deleted_objects:
                print(problem)
                problem.delete()

            if started_changed:
                exam.update_problems()

            return redirect('course:calendar', course_id)
        else:
            return self.render_to_response({
                'view': self,
                'form': form,
                'formset': formset,
            })


class ExamScoreView(SidebarMixin, UserCourseRelatedMixin, TemplateView):
    template_name = 'exam/score.html'
    exam = None
    section_title = 'Score exam'
    comments = None
    task = None

    def dispatch(self, request, exam_paper_id):
        self.exam_paper = get_object_or_404(ExamPaper, id=exam_paper_id,)
        self.exam = self.exam_paper.exam
        self.course = self.exam.course
        self.course_id = self.course.id

        self.task = Task.objects.filter(
                ttype=Task.EXAM_PAPER, assignee=request.user,
                exam_paper=self.exam_paper).first()

        return super(ExamScoreView, self).dispatch(
            request, exam_paper_id)

    def get(self, request, exam_paper_id):
        Answer.objects.init_answer(self.exam_paper)

        return self.render_to_response({
            'view': self,
            'exam': self.exam_paper.exam,
            'exam_paper_id': exam_paper_id,
            'student_id': self.exam_paper.student.id,
        })

    def post(self, request, exam_paper_id):
        if 'answer_pk' in request.POST:
            answer = Answer.objects.get(pk=request.POST.get("answer_pk"))
            answer.comment = request.POST.get("comment")
            answer.score = request.POST.get('score')
            answer.save()
        else:
            exam_paper = self.exam_paper
            exam_paper.total_score = request.POST.get('total_score')
            exam_paper.comment = request.POST.get('total_comment')
            exam_paper.save()

        return self.render_to_response({
            'view': self,
            'exam': self.exam_paper.exam,
            'exam_paper_id': exam_paper_id,
            'student_id': self.exam_paper.student.id,
        })


class ExamClassView(
        UserCourseRelatedMixin, SidebarMixin,
        ListView, PageinatorMixin):

    course = None
    section_title = 'Manage Class Exams'
    taskselect = None
    template_name = 'exam/class_view.html'
    context_object_name = 'user_list'

    @property
    def search_url(self):
        return 'exam:class_view'

    @property
    def search_url_para(self):
        return self.course.id

    def __init__(self, **kwargs):
        super(ExamClassView, self).__init__(**kwargs)

    def dispatch(self, request, pk):
        self.course = get_object_or_404(Course, id=pk)
        self.course_id = pk
        self.taskselect = SelectAssigneeForm()
        return super(ExamClassView, self).dispatch(request, pk)

    def get_queryset(self):
        queryset = self.course.students.all()
        queryset = super(ExamClassView, self).filter_queryset(
            queryset)
        return queryset

    def render_to_response(self, context, **response_kwargs):
        return super(ExamClassView, self).render_to_response(
            context, **response_kwargs
        )

    def get_context_data(self, **kwargs):
        context = super(ExamClassView, self).get_context_data(**kwargs)

        q = self.request.GET.get('q')
        if q:
            context['q'] = q

        context['exams'] = self.course.exams.all()

        return context
